package com.simple.relaxed.anno.impl;

import com.simple.relaxed.agent.TaskHandler;
import com.simple.relaxed.anno.TaskClass;
import com.simple.relaxed.manager.impl.InjectManager;
import com.simple.relaxed.manager.impl.TaskClassManager;
import com.simple.relaxed.utils.ReflectionsUtil;
import ohos.app.Context;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Set;

public class TaskClassImpl {

    /**
     * 全局搜索被@TaskClass注解标记的类，并且实例化，生成对应的Proxy类，替换掉InjectManager中符合要求的原始对象。
     * @param context 上下文对象
     */
    public static void taskClassImpl(Context context) {
        Map<String, Object> lookup = InjectManager.getInstance().lookup();
        for (Map.Entry<String, Object> entry : lookup.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            Class<?> aClass = value.getClass();
            TaskClass taskClass = aClass.getDeclaredAnnotation(TaskClass.class);
            if (taskClass == null) {
                continue;
            }
            String iName = taskClass.iName();
            Class<?>[] iClass = null;
            if (iName.isEmpty()) {
                iClass = aClass.getInterfaces();
            } else {
                try {
                    iClass = new Class[]{Class.forName(iName)};
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                    continue;
                }
            }
            Object instance = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), iClass, new TaskHandler(context, value));
            InjectManager.getInstance().update(key, instance);
        }
    }

    private static Object createObject(Context context, Class<?> aClass, String methodName) {
        if (methodName == null) {
            try {
                Constructor<?> constructor = aClass.getDeclaredConstructor(Context.class);
                constructor.setAccessible(true);
                return constructor.newInstance(context);
            } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
                try {
                    Constructor<?> constructor = aClass.getDeclaredConstructor();
                    constructor.setAccessible(true);
                    return constructor.newInstance();
                } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException noSuchMethodException) {
                    return null;
                }
            }
        } else {
            try {
                Method method = aClass.getDeclaredMethod(methodName, Context.class);
                method.setAccessible(true);
                return method.invoke(null, context);
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                try {
                    Method method = aClass.getDeclaredMethod(methodName);
                    method.setAccessible(true);
                    return method.invoke(null);
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException noSuchMethodException) {
                    return null;
                }
            }
        }
    }
}
